package net.danielthompson.danray;

import net.danielthompson.danray.cameras.*;
import net.danielthompson.danray.cameras.apertures.Aperture;
import net.danielthompson.danray.cameras.apertures.CircleAperture;
import net.danielthompson.danray.cameras.apertures.SquareAperture;
import net.danielthompson.danray.imports.WavefrontObjectImporter;
import net.danielthompson.danray.lights.OmniLight;
import net.danielthompson.danray.lights.Radiatable;
import net.danielthompson.danray.shading.Material;
import net.danielthompson.danray.shapes.*;
import net.danielthompson.danray.structures.*;
import net.danielthompson.danray.structures.Point;

import java.awt.*;
import java.io.File;

/**
 * User: daniel
 * Date: 6/30/13
 * Time: 9:53
 */
public class SceneBuilder {

   public static Scene OneSphere(int x, int y) {

      Scene scene = new Scene(null);

      Material material = new Material();

      material.setColor(Color.blue);

      Sphere sphere = new Sphere(material);
      sphere.Origin = new Point(x / 2, y / 2, -300.0);
      sphere.Radius = 100;

      scene.AddDrawableObject(sphere);

      Point lightOrigin = new Point(x / 2, y / 2, 100);
      double lumens = 1.0;

      Radiatable light = new OmniLight(lightOrigin, lumens);
      scene.AddRadiatableObject(light);

      return scene;
   }

   public static Scene Default() {

      Scene scene = new Scene(null);

      Material material = new Material();

      material.setColor(Color.blue);

      Sphere sphere1 = new Sphere(material);
      sphere1.Origin = new Point(50.0, 50.0, 40.0);
      sphere1.Radius = 10;

      scene.AddDrawableObject(sphere1);

      material = new Material();
      material.setColor(new Color(255, 255, 128));

      Sphere sphere2 = new Sphere(material);
      sphere2.Origin = new Point(0.0, 0.0, 20.0);
      sphere2.Radius = 55;

      scene.AddDrawableObject(sphere2);

      material = new Material();
      material.setColor(Color.green);

      Sphere sphere3 = new Sphere(material);
      sphere3.Origin = new Point(200.0, 200.0, 25.0);
      sphere3.Radius = 40;

      scene.AddDrawableObject(sphere3);

      return scene;
   }

   public static Scene DepthOfFieldTest(int x, int y) {
      Point origin = new Point(100, 75, 700);
      Point direction = new Point(0, -.35, -1);
      Vector orientation = new Vector(origin, direction);

      int focalLength = 1200;
      double rotation = 0.0;
      double zoomFactor = 1;
      double focusDistance = 500.0;

      Aperture aperture = new CircleAperture(20);

      Camera camera = new DepthOfFieldCamera(x, y, focalLength, rotation, zoomFactor, focusDistance, aperture, orientation);

      Scene scene = new Scene(camera);

      // floor orange plane
      Point planeOrigin = new Point(0, -250, 0);
      Point planeNormal = new Point(0, 1, 0);

      Vector planeNormal1 = new Vector(planeOrigin, planeNormal);

      Material material = new Material();
      material.setColor(new Color(255, 240, 185));
      material.setDiffuse(.5);
      material.setReflectivity(.5);

      ImplicitPlane plane = new ImplicitPlane(planeOrigin, planeNormal1, material);
      scene.AddDrawableObject(plane);

      // spheres

      for (int i = 0; i < 9; i++) {
         material = new Material();
         material.setColor(new Color(0, 131, 255));
         material.setDiffuse(.5);
         material.setReflectivity(.5);

         Sphere sphere = new Sphere(material);
         int coord = -850 + (175 * i);
         sphere.Origin = new Point(coord, 0, coord);
         sphere.Radius = 100;
         scene.AddDrawableObject(sphere);

         //scene.AddRadiatableObject(new OmniLight(new Point(-450 + (300 * i), 2000, -450 + (300 * i)), 25));
      }

      scene.AddRadiatableObject(new OmniLight(new Point(-650, 600, 925), 40));

      for (int i = 0; i < 1; i++) {
         scene.AddRadiatableObject(new OmniLight(new Point(0, 3000, -175 + (i * 300)), 200));
      }
      return scene;
   }

   public static Scene PlaneAndBox(int x, int y) {
      Point origin = new Point(200, 500, 400);
      Point direction = new Point(.2, .2, -1);
      Vector orientation = new Vector(origin, direction);

      int focalLength = 600;
      double rotation = 0.0;
      double zoomFactor = 3/4.0;
      double focusDistance = 100.0;

      Aperture aperture = new SquareAperture(20);

      Camera camera = new DepthOfFieldCamera(x, y, focalLength, rotation, zoomFactor, focusDistance, aperture, orientation);

      Scene scene = new Scene(camera);

      scene.AddRadiatableObject(new OmniLight(new Point(400, 400, 600), 15.7));
      scene.AddRadiatableObject(new OmniLight(new Point(300, 300, 600), 15.7));

      Material material = new Material();


      // horizontal orange plane
      Point planeOrigin = new Point(0, 1000, 0);
      Point planeNormal = new Point(0, 1, 0);

      Vector planeNormal1 = new Vector(planeOrigin, planeNormal);

      material = new Material();
      material.setColor(new Color(182, 73, 38));
      material.setDiffuse(.8);
      material.setReflectivity(.2);

      ImplicitPlane plane = new ImplicitPlane(planeOrigin, planeNormal1, material);
      scene.AddDrawableObject(plane);

      // horizontal orange plane
      planeOrigin = new Point(0, 0, 0);
      planeNormal = new Point(0, 1, 0);

      planeNormal1 = new Vector(planeOrigin, planeNormal);

      material = new Material();
      material.setColor(new Color(255, 131, 0));
      material.setDiffuse(.8);
      material.setReflectivity(.2);

      plane = new ImplicitPlane(planeOrigin, planeNormal1, material);
      scene.AddDrawableObject(plane);

      // white vertical z plane

      planeOrigin = new Point(0, 0, -400);
      planeNormal = new Point(0, 0, 1);

      planeNormal1 = new Vector(planeOrigin, planeNormal);

      material = new Material();
      material.setColor(new Color(255, 240, 185));
      material.setDiffuse(.5);
      material.setReflectivity(.5);

      plane = new ImplicitPlane(planeOrigin, planeNormal1, material);
      scene.AddDrawableObject(plane);

      // white vertical z plane

      planeOrigin = new Point(0, 0, 1000);
      planeNormal = new Point(0, 0, 1);

      planeNormal1 = new Vector(planeOrigin, planeNormal);

      material = new Material();
      material.setColor(new Color(255, 240, 185));
      material.setDiffuse(.5);
      material.setReflectivity(.5);

      plane = new ImplicitPlane(planeOrigin, planeNormal1, material);
      //scene.AddDrawableObject(plane);

      // white vertical x plane

      planeOrigin = new Point(800, 0, 0);
      planeNormal = new Point(-1, 0, 0);

      planeNormal1 = new Vector(planeOrigin, planeNormal);

      material = new Material();
      material.setColor(new Color(255, 240, 185));
      material.setDiffuse(.5);
      material.setReflectivity(.5);

      plane = new ImplicitPlane(planeOrigin, planeNormal1, material);
      scene.AddDrawableObject(plane);

      // blue vertical x plane

      planeOrigin = new Point(-200, 0, 0);
      planeNormal = new Point(1, 0, 0);

      planeNormal1 = new Vector(planeOrigin, planeNormal);

      material = new Material();
      material.setColor(new Color(0, 131, 255));
      material.setDiffuse(.8);
      material.setReflectivity(.2);

      plane = new ImplicitPlane(planeOrigin, planeNormal1, material);
      scene.AddDrawableObject(plane);

      // box

      material = new Material();
      material.setColor(new Color(131, 131, 255));
      material.setDiffuse(.8);
      material.setReflectivity(.2);

      Box box = new Box(new Point(250, 550, 250), new Point(350, 650, 350), material);
      scene.AddDrawableObject(box);

      return scene;
   }


   public static Scene ManySpheres(int x, int y) {
      Point origin = new Point(300, -100, 75);
      Point direction = new Point(0, 1, -.3);
      Vector orientation = new Vector(origin, direction);

      int focalLength = 600;
      double rotation = 20.0;
      double zoomFactor = 1/4.0;
      double focusDistance = 250.0;

      Aperture aperture = new SquareAperture(5);

      Camera camera = new DepthOfFieldCamera(x, y, focalLength, rotation, zoomFactor, focusDistance, aperture, orientation);

      Scene scene = new Scene(camera);

      // white vertical z plane

      Point planeOrigin = new Point(0, 0, 0);
      Point planeNormal = new Point(0, 0, 1);

      Vector planeNormal1 = new Vector(planeOrigin, planeNormal);

      Material material = new Material();
      material.setColor(new Color(255, 240, 185));
      material.setDiffuse(.75);
      material.setReflectivity(.25);

      ImplicitPlane plane = new ImplicitPlane(planeOrigin, planeNormal1, material);
      scene.AddDrawableObject(plane);

      for (int i = 0; i < 40; i++) {

         double originX = Math.random() * 600;
         double originY = Math.random() * 600;
         double originZ = Math.random() * 10 + 20;

         material = new Material();


         material.setColor(new Color(0, 131, 255));
         material.setReflectivity(.2);
         material.setTransparency(0);
         material.setDiffuse(.8);
         //material.setIndexOfRefraction(1.1);

         Sphere sphere = new Sphere(material);
         sphere.Origin = new Point(originX, originY, originZ);
         sphere.Radius = Math.random() * 50;
         scene.AddDrawableObject(sphere);
      }

      int maxSmallSpheresX = 15;
      int sphereXInterval = 40;

      int maxSmallSpheresY = 15;
      int sphereYInterval = 40;

      for (int i = 0; i < maxSmallSpheresX; i++) {
         for (int j = 0; j < maxSmallSpheresY; j++) {


            int constant = 128;

            int red = (int)(Math.random() * (255 - constant) + constant);
            int green = (int)(Math.random() * (255 - constant) + constant);
            int blue = (int)(Math.random() * (255 - constant) + constant);

            Color color = new Color(red, green, blue);
            /*
            Color color = null;
            double chance = Math.random();

            material = new Material();

            if (chance < .2) {
               color = new Color(0, 131, 255);
            }
            else if (chance < .4) {
               //color = new Color(182, 73, 38);
               color = new Color(255, 176, 59);
            }

            else if (chance < .6) {
               color = new Color(70, 137, 102);
            }
            else if (chance < .8) {
               color = new Color(255, 240, 185);
            }
            else {
               color = new Color(255, 176, 59);
            }*/
            material = new Material();
            material.setColor(color);
            material.setReflectivity(.3);
            material.setTransparency(0);
            material.setDiffuse(.7);

            Sphere sphere = new Sphere(material);

            double originX = sphereXInterval * i + Math.random() * 5 - 10;
            double originY = sphereYInterval * j + Math.random() * 5 - 10;
            double originZ = Math.random() * 5 + 60;

            sphere.Origin = new Point(originX, originY, originZ);
            sphere.Radius = Math.random() * 5 + 5;
            scene.AddDrawableObject(sphere);
         }
      }

      scene.AddRadiatableObject(new OmniLight(new Point(300, 300, 300), 5.7));

      //scene.AddRadiatableObject(new OmniLight(new Point(x / 20, y / 2, -100), 5.7));
      //scene.AddRadiatableObject(new OmniLight(new Point(19 * x / 20, y / 2, -100), 5.7));
      //scene.AddRadiatableObject(new OmniLight(new Point(x / 2, 3 * y / 4, -100), 5.7));

      //scene.AddRadiatableObject(new OmniLight(new Point(x / 2, y / 2, 300), 5.9));
      scene.AddRadiatableObject(new OmniLight(new Point(x / 2, y / 2, 600), 10.0));

      return scene;
   }

   public static Scene TwoSpheresWithLights(int x, int y) {
      Scene scene = new Scene(null);

      Material material = new Material();
      material.setColor(Color.blue);
      material.setDiffuse(0);
      material.setReflectivity(0);

      Sphere sphere = new Sphere(material);
      sphere.Origin = new Point(x / 3, y / 2, 0.0);
      sphere.Radius = y / 4;

      scene.AddDrawableObject(sphere);

      material = new Material();
      material.setColor(Color.red);
      material.setDiffuse(0);
      material.setReflectivity(0);

      sphere = new Sphere(material);
      sphere.Origin = new Point(2 * x / 3, y / 2, 0.0);
      sphere.Radius = y / 4;

      scene.AddDrawableObject(sphere);

      //Point lightOrigin = new Point(x / 2, y / 2, 400);
      //double lumens = 1.0;

      //Radiatable light = new OmniLight(lightOrigin, lumens);
      //scene.AddRadiatableObject(light);

      //scene.AddRadiatableObject(new OmniLight(new Point(x / 3, y / 3, 300), 0.5));
      //scene.AddRadiatableObject(new OmniLight(new Point(x / 2, y / 4, -100), 0.7));
      //scene.AddRadiatableObject(new OmniLight(new Point(x / 20, y / 2, -100), 0.8));
      //scene.AddRadiatableObject(new OmniLight(new Point(19 * x / 20, y / 2, -100), 0.9));
      //scene.AddRadiatableObject(new OmniLight(new Point(x / 2, 3 * y / 4, -100), 0.8));

      scene.AddRadiatableObject(new OmniLight(new Point(x / 2, y / 2, 300), 1.0));
      return scene;


   }

   public static Scene ShadowTest(int x, int y) {
      Scene scene = new Scene(null);

      Material material = new Material();
      material.setColor(Color.blue);
      material.setDiffuse(0);
      material.setReflectivity(.75);

      Sphere sphere = new Sphere(material);
      sphere.Origin = new Point(x / 2, y / 2, 0.0);
      sphere.Radius = 300;

      scene.AddDrawableObject(sphere);

      material = new Material();
      material.setColor(Color.red);
      material.setDiffuse(0);
      material.setReflectivity(.75);

      sphere = new Sphere(material);
      sphere.Origin = new Point(x / 2 + 40, y / 2 + 40, 400);
      sphere.Radius = 10;

      scene.AddDrawableObject(sphere);

      scene.AddRadiatableObject(new OmniLight(new Point(x / 2, y / 2, 600), 5.0));

      //scene.AddRadiatableObject(new OmniLight(new Point(3 * x / 5, y / 2, 700), 5.0));
      return scene;
   }

   public static Scene ReflectiveSphereWithLights(int x, int y) {
      Scene scene = new Scene(null);

      Material material = new Material();
      material.setColor(Color.blue);
      material.setDiffuse(.5);
      material.setReflectivity(.75);

      Sphere sphere = new Sphere(material);
      sphere.Origin = new Point(x / 3, y / 3, 0.0);
      sphere.Radius = y / 4;

      scene.AddDrawableObject(sphere);

      material = new Material();
      material.setColor(Color.red);
      material.setDiffuse(.5);
      material.setReflectivity(.75);

      sphere = new Sphere(material);
      sphere.Origin = new Point(2 * x / 3, 2 * y / 3, 0.0);
      sphere.Radius = y / 4;

      scene.AddDrawableObject(sphere);

      scene.AddRadiatableObject(new OmniLight(new Point(x / 2, y / 2, 500), 10.0));

      return scene;
   }

   public static Scene ReflectiveTriangleWithLight(int x, int y) {
      Scene scene = new Scene(null);

      Point vertex1 = new Point(x / 3, 3 * y / 5, 0);
      Point vertex2 = new Point(2 * x / 3, 3 * y / 5, 0);
      Point vertex3 = new Point(x / 2, y / 4, 400);
      Material material = new Material();
      material.setColor(new Color(255, 131, 0));

      Triangle triangle = new Triangle(vertex1, vertex2, vertex3, material);

      Point planeOrigin = new Point(0, 0, 0);
      Point planeNormal = new Point(0, 0, -1);

      Vector planeNormal1 = new Vector(planeOrigin, planeNormal);

      material = new Material();
      material.setColor(new Color(131, 255, 0));
      material.setDiffuse(.5);
      material.setReflectivity(.75);

      ImplicitPlane plane = new ImplicitPlane(planeOrigin, planeNormal1, material);
      scene.AddDrawableObject(plane);

      scene.AddDrawableObject(triangle);

      scene.AddRadiatableObject(new OmniLight(new Point(x / 3, y / 2, 500), 20.0));

      return scene;
   }

   public static Scene ReflectiveTriangleMeshWithLight(int x, int y) {
      Scene scene = new Scene(null);

      // teapot

      WavefrontObjectImporter importer = new WavefrontObjectImporter(new File("models/teapot.obj"));
      Material material = new Material();
      material.setColor(new Color(182, 73, 38));
      material.setDiffuse(.5);
      material.setReflectivity(.5);
      material.setTransparency(0);

      TriangleMesh mesh = importer.Process();
      mesh.SetMaterial(material);
      mesh.SetRotation(new Tuple(160, 20, 20));
      mesh.SetOrigin(new Point(2 * x / 3, y / 2, 400));

      scene.AddDrawableObject(mesh);
/*
      // sphere

      material = new Material();
      material.setColor(new Color(70, 137, 102));
      material.setDiffuse(.33);
      material.setReflectivity(.33);
      material.setTransparency(.33);
      material.setIndexOfRefraction(1.333);

      Sphere sphere = new Sphere(material);
      sphere.Origin = new Point(2 * x / 5, y / 3, 400.0);
      sphere.Radius = y / 6;

      scene.AddDrawableObject(sphere);

      // plane

      Point planeOrigin = new Point(0, 0, 0);
      Point planeNormal = new Point(0, 0, -1);

      Vector planeNormal1 = new Vector(planeOrigin, planeNormal);

      material = new Material();
      material.setColor(new Color(182, 73, 38));
      material.setDiffuse(.5);
      material.setReflectivity(.5);

      ImplicitPlane plane = new ImplicitPlane(planeOrigin, planeNormal1, material);
      scene.AddDrawableObject(plane);
*/
      // lights

      scene.AddRadiatableObject(new OmniLight(new Point(x / 3, y / 2, 900), 20.0));
      scene.AddRadiatableObject(new OmniLight(new Point(2 * x / 3, 2 * y / 3, 900), 20.0));
      return scene;
   }

   public static Scene FourReflectiveSphereWithLights(int x, int y) {

      Point rearFocalPoint = new Point(x/4, y/2, 2000);

      Camera camera = new SimpleStochasticCamera(rearFocalPoint);
      //Vector orientation = new Vector(new Point(x/2, y/2, 1600), new Point(0, 0, -1));

      Scene scene = new Scene(camera);

      Material material = new Material();
      material.setColor(new Color(70, 137, 102));
      material.setDiffuse(.33);
      material.setReflectivity(.33);
      material.setTransparency(.33);
      material.setIndexOfRefraction(1.333);

      Sphere sphere = new Sphere(material);
      sphere.Origin = new Point(2 * x / 5, y / 3, -200.0);
      sphere.Radius = y / 6;

      scene.AddDrawableObject(sphere);

      material = new Material();
      material.setColor(new Color(70, 137, 102));
      material.setDiffuse(.2);
      material.setReflectivity(0);
      material.setTransparency(.8);
      material.setIndexOfRefraction(1.2);

      sphere = new Sphere(material);
      sphere.Origin = new Point(x/2, y/2, 600.0);
      sphere.Radius = y / 2;

      //scene.AddDrawableObject(sphere);

      material = new Material();
      material.setColor(new Color(255, 240, 185));
      material.setDiffuse(.34);
      material.setReflectivity(.33);
      material.setTransparency(.33);
      material.setIndexOfRefraction(1.0);

      sphere = new Sphere(material);
      sphere.Origin = new Point(3 * x / 5, 2 * y / 3, 200.0);
      sphere.Radius = y / 6;

      scene.AddDrawableObject(sphere);

      material = new Material();
      material.setColor(new Color(255, 176, 59));
      material.setReflectivity(.5);
      material.setDiffuse(.5);

      sphere = new Sphere(material);
      sphere.Origin = new Point(x / 5, 2 * y / 3, 0.0);
      sphere.Radius = y / 6;

      scene.AddDrawableObject(sphere);

      material = new Material();
      material.setColor(new Color(182, 73, 38));
      material.setReflectivity(.5);
      material.setDiffuse(.5);

      sphere = new Sphere(material);
      sphere.Origin = new Point(4 * x / 5, y / 3, 0.0);
      sphere.Radius = y / 6;

      scene.AddDrawableObject(sphere);

      material = new Material();
      material.setColor(new Color(142, 40, 0));
      material.setReflectivity(.5);
      material.setDiffuse(.5);

      sphere = new Sphere(material);
      sphere.Origin = new Point(x / 5, y / 2, 200.0);
      sphere.Radius = y / 25;

      scene.AddDrawableObject(sphere);

      Point planeOrigin = new Point(0, 3 * y / 4, 0);
      Point planeNormal = new Point(0, -1, 0);

      Vector planeNormal1 = new Vector(planeOrigin, planeNormal);

      material = new Material();
      material.setColor(new Color(255, 131, 0));
      material.setDiffuse(.5);
      material.setReflectivity(.5);

      ImplicitPlane plane = new ImplicitPlane(planeOrigin, planeNormal1, material);
      scene.AddDrawableObject(plane);

      planeOrigin = new Point(0, 0, -400);
      planeNormal = new Point(0, 0, 1);

      planeNormal1 = new Vector(planeOrigin, planeNormal);

      material = new Material();
      material.setColor(new Color(255, 240, 185));
      material.setDiffuse(.75);
      material.setReflectivity(.25);

      plane = new ImplicitPlane(planeOrigin, planeNormal1, material);
      scene.AddDrawableObject(plane);

      planeOrigin = new Point(x / 5, 0, 0);
      planeNormal = new Point(1, 0, 0);

      planeNormal1 = new Vector(planeOrigin, planeNormal);

      material = new Material();
      material.setColor(new Color(0, 131, 255));
      material.setDiffuse(.75);
      material.setReflectivity(.25);

      plane = new ImplicitPlane(planeOrigin, planeNormal1, material);
      scene.AddDrawableObject(plane);

      planeOrigin = new Point(4 * x / 5, 0, 0);
      planeNormal = new Point(-1, 0, 0);

      planeNormal1 = new Vector(planeOrigin, planeNormal);

      material = new Material();
      material.setColor(new Color(255, 240, 185));
      material.setDiffuse(.75);
      material.setReflectivity(.25);

      plane = new ImplicitPlane(planeOrigin, planeNormal1, material);
      scene.AddDrawableObject(plane);

      //scene.AddRadiatableObject(new OmniLight(new Point(x / 6, 8 * y / 12, 600), 5.0));
      //scene.AddRadiatableObject(new OmniLight(new Point(x / 2, 2 * y / 3, 600), 5.0));
      scene.AddRadiatableObject(new OmniLight(new Point(x / 2, y / 2, 500), 25.0));
      //scene.AddRadiatableObject(new OmniLight(new Point(5 * x / 7, 2 * y / 3, -350), 2.0));
      scene.AddRadiatableObject(new OmniLight(new Point(3 * x / 5, y / 3, -200), 2.0));
      return scene;
   }


   public static Scene FourReflectiveSphereWithLightsPointable(int x, int y) {

      Point origin = new Point(300, 300, 2500);
      Point direction = new Point(0, 0, -1);
      Vector orientation = new Vector(origin, direction);

      int focalLength = 1200;
      double rotation = 100.0;
      double zoomFactor = 1.0;
      double focusDistance = 1487.0;

      Aperture aperture = new CircleAperture(50);

      Camera camera = new DepthOfFieldCamera(x, y, focalLength, rotation, zoomFactor, focusDistance, aperture, orientation);

      //Vector orientation = new Vector(new Point(x/2, y/2, 1600), new Point(0, 0, -1));

      Scene scene = new Scene(camera);

      // lights

      scene.AddRadiatableObject(new OmniLight(new Point(160, 360, 600), 5.0));
      scene.AddRadiatableObject(new OmniLight(new Point(480, 360, 600), 5.0));
      scene.AddRadiatableObject(new OmniLight(new Point(300, 300, 300), 5.0));
      scene.AddRadiatableObject(new OmniLight(new Point(300, 300, 1500), 10.0));
      //scene.AddRadiatableObject(new OmniLight(new Point(685, 360, -350), 5.0));
      scene.AddRadiatableObject(new OmniLight(new Point(575, 180, -200), 5.0));

      Material material = new Material();
      // horizontal orange plane



      Point planeOrigin = new Point(0, 0, 0);
      Point planeNormal = new Point(0, 1, 0);

      Vector planeNormal1 = new Vector(planeOrigin, planeNormal);

      material = new Material();
      material.setColor(new Color(255, 131, 0));
      material.setDiffuse(.9);
      material.setReflectivity(.1);

      ImplicitPlane plane = new ImplicitPlane(planeOrigin, planeNormal1, material);
      scene.AddDrawableObject(plane);

      // white vertical z plane

      planeOrigin = new Point(0, 0, -400);
      planeNormal = new Point(0, 0, 1);

      planeNormal1 = new Vector(planeOrigin, planeNormal);

      material = new Material();
      material.setColor(new Color(255, 240, 185));
      material.setDiffuse(.75);
      material.setReflectivity(.25);

      plane = new ImplicitPlane(planeOrigin, planeNormal1, material);
      scene.AddDrawableObject(plane);

      // white vertical x plane

      planeOrigin = new Point(800, 0, 0);
      planeNormal = new Point(-1, 0, 0);

      planeNormal1 = new Vector(planeOrigin, planeNormal);

      material = new Material();
      material.setColor(new Color(255, 240, 185));
      material.setDiffuse(.75);
      material.setReflectivity(.25);

      plane = new ImplicitPlane(planeOrigin, planeNormal1, material);
      scene.AddDrawableObject(plane);

      // blue vertical x plane

      planeOrigin = new Point(-200, 0, 0);
      planeNormal = new Point(1, 0, 0);

      planeNormal1 = new Vector(planeOrigin, planeNormal);

      material = new Material();
      material.setColor(new Color(0, 131, 255));
      material.setDiffuse(.9);
      material.setReflectivity(.1);

      plane = new ImplicitPlane(planeOrigin, planeNormal1, material);
      scene.AddDrawableObject(plane);


      // green sphere

      material = new Material();
      material.setColor(new Color(70, 137, 102));
      material.setDiffuse(.5);
      material.setReflectivity(.5);
      material.setTransparency(0);
      material.setIndexOfRefraction(1.2);

      Sphere sphere = new Sphere(material);
      sphere.Origin = new Point(200, 350, -100.0);
      sphere.Radius = 150;

      scene.AddDrawableObject(sphere);

      // white sphere

      material = new Material();
      material.setColor(new Color(255, 240, 185));
      material.setDiffuse(.1);
      material.setReflectivity(.3);
      material.setTransparency(.6);
      material.setIndexOfRefraction(1.3);

      sphere = new Sphere(material);
      sphere.Origin = new Point(500, 100, 600.0);
      sphere.Radius = 150;

      scene.AddDrawableObject(sphere);

      // big dark orange sphere

      material = new Material();
      material.setColor(new Color(182, 73, 38));
      material.setReflectivity(.5);
      material.setDiffuse(.5);

      sphere = new Sphere(material);
      sphere.Origin = new Point(800, 350, 1000.0);
      sphere.Radius = 150;

      scene.AddDrawableObject(sphere);

      //

      // orange sphere

      material = new Material();
      material.setColor(new Color(255, 176, 59));
      material.setReflectivity(.5);
      material.setDiffuse(.5);

      sphere = new Sphere(material);
      sphere.Origin = new Point(-200, 100, 1000);
      sphere.Radius = 150;

      scene.AddDrawableObject(sphere);

      // tiny red sphere

      material = new Material();
      material.setColor(new Color(142, 40, 0));
      material.setReflectivity(.5);
      material.setDiffuse(.5);

      sphere = new Sphere(material);
      sphere.Origin = new Point(160, 300, 200.0);
      sphere.Radius = 25;

      scene.AddDrawableObject(sphere);

      // tiny blue sphere

      material = new Material();
      material.setColor(new Color(62, 96, 111));
      material.setReflectivity(.6);
      material.setDiffuse(.4);

      sphere = new Sphere(material);
      sphere.Origin = new Point(250, 300, 200.0);
      sphere.Radius = 25;

      scene.AddDrawableObject(sphere);

      return scene;
   }

   public static Scene TwoTransparentReflectiveSpheresWithLights(int x, int y) {
      Scene scene = new Scene(null);

      Material material = new Material();
      material.setColor(Color.blue);
      material.setReflectivity(.33);
      //material.setTransparency(.33);
      //material.setIndexOfRefraction(1.333);

      Sphere sphere = new Sphere(material);
      sphere.Origin = new Point(2 * x / 5, y / 3, 500.0);
      sphere.Radius = y / 5;

      scene.AddDrawableObject(sphere);

      Point planeOrigin = new Point(0, 0, -400);
      Point planeNormal = new Point(0, 0, 1);

      Vector planeNormal1 = new Vector(planeOrigin, planeNormal);

      material = new Material();
      material.setColor(new Color(255, 131, 0));
      //material.setDiffuse(.5);
      //material.setReflectivity(0);

      ImplicitPlane plane = new ImplicitPlane(planeOrigin, planeNormal1, material);
      scene.AddDrawableObject(plane);

      scene.AddRadiatableObject(new OmniLight(new Point(x / 2, y / 2, 500), 25.0));

      return scene;
   }
}